{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bea74a38-86dd-49f8-8973-59f774f32a40",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Usage: ipykernel_launcher.py -b BASE -t TEXTURE -o OUTPUT [-w WAVELET] [-l LEVEL] [-m MODE]\n",
      "\n",
      "ipykernel_launcher.py: error: no such option: -f\n",
      "ERROR:root:Internal Python error in the inspect module.\n",
      "Below is the traceback from this internal error.\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Traceback (most recent call last):\n",
      "  File \"/usr/lib/python3.8/optparse.py\", line 1387, in parse_args\n",
      "    stop = self._process_args(largs, rargs, values)\n",
      "  File \"/usr/lib/python3.8/optparse.py\", line 1431, in _process_args\n",
      "    self._process_short_opts(rargs, values)\n",
      "  File \"/usr/lib/python3.8/optparse.py\", line 1513, in _process_short_opts\n",
      "    raise BadOptionError(opt)\n",
      "optparse.BadOptionError: no such option: -f\n",
      "\n",
      "During handling of the above exception, another exception occurred:\n",
      "\n",
      "Traceback (most recent call last):\n",
      "  File \"/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py\", line 3441, in run_code\n",
      "    exec(code_obj, self.user_global_ns, self.user_ns)\n",
      "  File \"/tmp/ipykernel_48815/2041144913.py\", line 186, in <module>\n",
      "    main()\n",
      "  File \"/tmp/ipykernel_48815/2041144913.py\", line 166, in main\n",
      "    (options, args) = parser.parse_args()\n",
      "  File \"/usr/lib/python3.8/optparse.py\", line 1389, in parse_args\n",
      "    self.error(str(err))\n",
      "  File \"/usr/lib/python3.8/optparse.py\", line 1569, in error\n",
      "    self.exit(2, \"%s: error: %s\\n\" % (self.get_prog_name(), msg))\n",
      "  File \"/usr/lib/python3.8/optparse.py\", line 1559, in exit\n",
      "    sys.exit(status)\n",
      "SystemExit: 2\n",
      "\n",
      "During handling of the above exception, another exception occurred:\n",
      "\n",
      "Traceback (most recent call last):\n",
      "  File \"/usr/local/lib/python3.8/dist-packages/IPython/core/ultratb.py\", line 1101, in get_records\n",
      "    return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)\n",
      "  File \"/usr/local/lib/python3.8/dist-packages/IPython/core/ultratb.py\", line 248, in wrapped\n",
      "    return f(*args, **kwargs)\n",
      "  File \"/usr/local/lib/python3.8/dist-packages/IPython/core/ultratb.py\", line 281, in _fixed_getinnerframes\n",
      "    records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))\n",
      "  File \"/usr/lib/python3.8/inspect.py\", line 1515, in getinnerframes\n",
      "    frameinfo = (tb.tb_frame,) + getframeinfo(tb, context)\n",
      "AttributeError: 'tuple' object has no attribute 'tb_frame'\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "object of type 'NoneType' has no len()",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mBadOptionError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[0;32m/usr/lib/python3.8/optparse.py\u001b[0m in \u001b[0;36mparse_args\u001b[0;34m(self, args, values)\u001b[0m\n\u001b[1;32m   1386\u001b[0m         \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1387\u001b[0;31m             \u001b[0mstop\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_process_args\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1388\u001b[0m         \u001b[0;32mexcept\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mBadOptionError\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mOptionValueError\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/lib/python3.8/optparse.py\u001b[0m in \u001b[0;36m_process_args\u001b[0;34m(self, largs, rargs, values)\u001b[0m\n\u001b[1;32m   1430\u001b[0m                 \u001b[0;31m# value(s) for the last one only)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1431\u001b[0;31m                 \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_process_short_opts\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1432\u001b[0m             \u001b[0;32melif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mallow_interspersed_args\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/lib/python3.8/optparse.py\u001b[0m in \u001b[0;36m_process_short_opts\u001b[0;34m(self, rargs, values)\u001b[0m\n\u001b[1;32m   1512\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0moption\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1513\u001b[0;31m                 \u001b[0;32mraise\u001b[0m \u001b[0mBadOptionError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mopt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1514\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0moption\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtakes_value\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mBadOptionError\u001b[0m: no such option: -f",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[0;31mSystemExit\u001b[0m                                Traceback (most recent call last)",
      "    \u001b[0;31m[... skipping hidden 1 frame]\u001b[0m\n",
      "\u001b[0;32m/tmp/ipykernel_48815/2041144913.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m    185\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 186\u001b[0;31m \u001b[0mmain\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/tmp/ipykernel_48815/2041144913.py\u001b[0m in \u001b[0;36mmain\u001b[0;34m()\u001b[0m\n\u001b[1;32m    165\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 166\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0moptions\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparser\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparse_args\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    167\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/lib/python3.8/optparse.py\u001b[0m in \u001b[0;36mparse_args\u001b[0;34m(self, args, values)\u001b[0m\n\u001b[1;32m   1388\u001b[0m         \u001b[0;32mexcept\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mBadOptionError\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mOptionValueError\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1389\u001b[0;31m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0merror\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1390\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/lib/python3.8/optparse.py\u001b[0m in \u001b[0;36merror\u001b[0;34m(self, msg)\u001b[0m\n\u001b[1;32m   1568\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mprint_usage\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstderr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1569\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"%s: error: %s\\n\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_prog_name\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1570\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/lib/python3.8/optparse.py\u001b[0m in \u001b[0;36mexit\u001b[0;34m(self, status, msg)\u001b[0m\n\u001b[1;32m   1558\u001b[0m             \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstderr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1559\u001b[0;31m         \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstatus\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1560\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mSystemExit\u001b[0m: 2",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "    \u001b[0;31m[... skipping hidden 1 frame]\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py\u001b[0m in \u001b[0;36mshowtraceback\u001b[0;34m(self, exc_tuple, filename, tb_offset, exception_only, running_compiled_code)\u001b[0m\n\u001b[1;32m   2052\u001b[0m                     stb = ['An exception has occurred, use %tb to see '\n\u001b[1;32m   2053\u001b[0m                            'the full traceback.\\n']\n\u001b[0;32m-> 2054\u001b[0;31m                     stb.extend(self.InteractiveTB.get_exception_only(etype,\n\u001b[0m\u001b[1;32m   2055\u001b[0m                                                                      value))\n\u001b[1;32m   2056\u001b[0m                 \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.8/dist-packages/IPython/core/ultratb.py\u001b[0m in \u001b[0;36mget_exception_only\u001b[0;34m(self, etype, value)\u001b[0m\n\u001b[1;32m    752\u001b[0m         \u001b[0mvalue\u001b[0m \u001b[0;34m:\u001b[0m \u001b[0mexception\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    753\u001b[0m         \"\"\"\n\u001b[0;32m--> 754\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0mListTB\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstructured_traceback\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0metype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    755\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    756\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mshow_exception_only\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0metype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mevalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.8/dist-packages/IPython/core/ultratb.py\u001b[0m in \u001b[0;36mstructured_traceback\u001b[0;34m(self, etype, evalue, etb, tb_offset, context)\u001b[0m\n\u001b[1;32m    627\u001b[0m             \u001b[0mchained_exceptions_tb_offset\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    628\u001b[0m             out_list = (\n\u001b[0;32m--> 629\u001b[0;31m                 self.structured_traceback(\n\u001b[0m\u001b[1;32m    630\u001b[0m                     \u001b[0metype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mevalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0metb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchained_exc_ids\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    631\u001b[0m                     chained_exceptions_tb_offset, context)\n",
      "\u001b[0;32m/usr/local/lib/python3.8/dist-packages/IPython/core/ultratb.py\u001b[0m in \u001b[0;36mstructured_traceback\u001b[0;34m(self, etype, value, tb, tb_offset, number_of_lines_of_context)\u001b[0m\n\u001b[1;32m   1365\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1366\u001b[0m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtb\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1367\u001b[0;31m         return FormattedTB.structured_traceback(\n\u001b[0m\u001b[1;32m   1368\u001b[0m             self, etype, value, tb, tb_offset, number_of_lines_of_context)\n\u001b[1;32m   1369\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.8/dist-packages/IPython/core/ultratb.py\u001b[0m in \u001b[0;36mstructured_traceback\u001b[0;34m(self, etype, value, tb, tb_offset, number_of_lines_of_context)\u001b[0m\n\u001b[1;32m   1265\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mmode\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mverbose_modes\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1266\u001b[0m             \u001b[0;31m# Verbose modes need a full traceback\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1267\u001b[0;31m             return VerboseTB.structured_traceback(\n\u001b[0m\u001b[1;32m   1268\u001b[0m                 \u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0metype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtb_offset\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnumber_of_lines_of_context\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1269\u001b[0m             )\n",
      "\u001b[0;32m/usr/local/lib/python3.8/dist-packages/IPython/core/ultratb.py\u001b[0m in \u001b[0;36mstructured_traceback\u001b[0;34m(self, etype, evalue, etb, tb_offset, number_of_lines_of_context)\u001b[0m\n\u001b[1;32m   1122\u001b[0m         \u001b[0;34m\"\"\"Return a nice text document describing the traceback.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1123\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1124\u001b[0;31m         formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,\n\u001b[0m\u001b[1;32m   1125\u001b[0m                                                                tb_offset)\n\u001b[1;32m   1126\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.8/dist-packages/IPython/core/ultratb.py\u001b[0m in \u001b[0;36mformat_exception_as_a_whole\u001b[0;34m(self, etype, evalue, etb, number_of_lines_of_context, tb_offset)\u001b[0m\n\u001b[1;32m   1080\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1081\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1082\u001b[0;31m         \u001b[0mlast_unique\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrecursion_repeat\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfind_recursion\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0morig_etype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mevalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrecords\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1083\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1084\u001b[0m         \u001b[0mframes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat_records\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrecords\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlast_unique\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrecursion_repeat\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.8/dist-packages/IPython/core/ultratb.py\u001b[0m in \u001b[0;36mfind_recursion\u001b[0;34m(etype, value, records)\u001b[0m\n\u001b[1;32m    380\u001b[0m     \u001b[0;31m# first frame (from in to out) that looks different.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    381\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mis_recursion_error\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0metype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrecords\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 382\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrecords\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    383\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    384\u001b[0m     \u001b[0;31m# Select filename, lineno, func_name to track frames with\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: object of type 'NoneType' has no len()"
     ]
    }
   ],
   "source": [
    "#!/usr/bin/env python\n",
    "\n",
    "# Copyright (c) 2006-2012 Filip Wasilewski <http://en.ig.ma/>\n",
    "# Copyright (c) 2012-2016 The PyWavelets Developers\n",
    "#                         <https://github.com/PyWavelets/pywt>\n",
    "# See COPYING for license details.\n",
    "\n",
    "\"\"\"\n",
    "Wavelet Image Blender.\n",
    "\n",
    "Blend image A with texture extracted from image B by selecting\n",
    "detail coefficients:\n",
    "\n",
    "    -----------------     -----------------\n",
    "    |               |     |               |\n",
    "    |               |     |               |\n",
    "    |               |     |               |\n",
    "    |       A       |     |       B       |\n",
    "    |               |     |               |\n",
    "    |               |     |               |\n",
    "    |               |     |               |\n",
    "    -----------------     -----------------\n",
    "\n",
    "            |                     |\n",
    "     2D DWT |              2D DWT |\n",
    "            V                     V\n",
    "\n",
    "    -----------------             ---------          -----------------\n",
    "    |       |       |             |       |          |               |\n",
    "    | A(LL) | H(LH) |             | H(LH) |          |               |\n",
    "    |       |       |             |       |   IDWT   |               |\n",
    "    -----------------  +  -----------------  ----->  |       C       |\n",
    "    |       |       |     |       |       |          |               |\n",
    "    | V(HL) | D(HH) |     | V(HL) | D(HH) |          |               |\n",
    "    |       |       |     |       |       |          |               |\n",
    "    -----------------     -----------------          -----------------\n",
    "                            (details only)\n",
    "\"\"\"\n",
    "\n",
    "import optparse\n",
    "import os\n",
    "import sys\n",
    "if os.name == 'nt':\n",
    "    from time import clock  # noqa\n",
    "else:\n",
    "    from time import time as clock  # noqa\n",
    "\n",
    "from PIL import Image  # PIL\n",
    "import numpy  # http://www.scipy.org\n",
    "\n",
    "import pywt\n",
    "\n",
    "\n",
    "def image2array(image):\n",
    "    \"\"\"PIL Image to NumPy array\"\"\"\n",
    "    assert image.mode in ('L', 'RGB', 'CMYK')\n",
    "    arr = numpy.fromstring(image.tobytes(), numpy.uint8)\n",
    "    arr.shape = (image.size[1], image.size[0], len(image.getbands()))\n",
    "    return arr.swapaxes(0, 2).swapaxes(1, 2).astype(numpy.float32)\n",
    "\n",
    "\n",
    "def array2image(arr, mode):\n",
    "    \"\"\"NumPy array to PIL Image\"\"\"\n",
    "    arr = arr.swapaxes(1, 2).swapaxes(0, 2)\n",
    "    arr[arr < 0] = 0\n",
    "    arr[arr > 255] = 255\n",
    "    arr = numpy.fix(arr).astype(numpy.uint8)\n",
    "    return Image.frombytes(mode, arr.shape[1::-1], arr.tobytes())\n",
    "\n",
    "\n",
    "def load_image(path, mode=None, size=None):\n",
    "    \"\"\"Load image\"\"\"\n",
    "    im = Image.open(path)\n",
    "\n",
    "    if im.mode not in ('L', 'P', 'RGB', 'CMYK'):\n",
    "        raise TypeError(\"Image mode must be 'L', 'P', 'RGB' or 'CMYK'\")\n",
    "\n",
    "    if mode is not None:\n",
    "        if mode == 'P':\n",
    "            raise ValueError(\"Mode must be 'L', 'RGB' or 'CMYK'\")\n",
    "        im = im.convert(mode)\n",
    "    elif im.mode == 'P':\n",
    "        im = im.convert('RGB')\n",
    "\n",
    "    if size is not None and im.size != size:\n",
    "        im = im.resize(size, Image.ANTIALIAS)\n",
    "    return im\n",
    "\n",
    "\n",
    "def blend_images(base, texture, wavelet, level, mode='smooth', base_gain=None,\n",
    "                 texture_gain=None):\n",
    "    \"\"\"Blend loaded images at `level` of granularity using `wavelet`\"\"\"\n",
    "\n",
    "    base_data = image2array(base)\n",
    "    texture_data = image2array(texture)\n",
    "    output_data = []\n",
    "\n",
    "    # process color bands\n",
    "    for base_band, texture_band in zip(base_data, texture_data):\n",
    "        # multilevel dwt\n",
    "        base_band_coeffs = pywt.wavedec2(base_band, wavelet, mode, level)\n",
    "        texture_band_coeffs = pywt.wavedec2(texture_band, wavelet, mode, level)\n",
    "\n",
    "        # average coefficients of base image\n",
    "        output_band_coeffs = [base_band_coeffs[0]]  # cA\n",
    "        del base_band_coeffs[0], texture_band_coeffs[0]\n",
    "\n",
    "        # blend details coefficients\n",
    "        for n, (base_band_details, texture_band_details) in enumerate(\n",
    "                zip(base_band_coeffs, texture_band_coeffs)):\n",
    "            blended_details = []\n",
    "            for (base_detail, texture_detail) in zip(base_band_details,\n",
    "                                                     texture_band_details):\n",
    "                if base_gain is not None:\n",
    "                    base_detail *= base_gain\n",
    "                if texture_gain is not None:\n",
    "                    texture_detail *= texture_gain\n",
    "\n",
    "                # select coeffs with greater energy\n",
    "                blended = numpy.where(abs(base_detail) > abs(texture_detail),\n",
    "                                      base_detail, texture_detail)\n",
    "                blended_details.append(blended)\n",
    "\n",
    "            base_band_coeffs[n] = texture_band_coeffs[n] = None\n",
    "            output_band_coeffs.append(blended_details)\n",
    "\n",
    "        # multilevel idwt\n",
    "        new_band = pywt.waverec2(output_band_coeffs, wavelet, mode)\n",
    "        output_data.append(new_band)\n",
    "        del new_band, base_band_coeffs, texture_band_coeffs\n",
    "\n",
    "    del base_data, texture_data\n",
    "    output_data = numpy.array(output_data)\n",
    "\n",
    "    return array2image(output_data, base.mode)\n",
    "\n",
    "\n",
    "def main():\n",
    "    usage = \"usage: %prog -b BASE -t TEXTURE -o OUTPUT \"\\\n",
    "            \"[-w WAVELET] [-l LEVEL] [-m MODE]\"\n",
    "    parser = optparse.OptionParser(usage=usage)\n",
    "    parser.add_option(\"-b\", \"--base\", dest=\"base\", metavar=\"BASE\",\n",
    "                      help=\"base image name\")\n",
    "    parser.add_option(\"-t\", \"--texture\", dest=\"texture\", metavar=\"TEXTURE\",\n",
    "                      help=\"texture image name\")\n",
    "    parser.add_option(\"-o\", \"--output\", dest=\"output\", metavar=\"OUTPUT\",\n",
    "                      help=\"output image name\")\n",
    "    parser.add_option(\"-w\", \"--wavelet\", dest=\"wavelet\", metavar=\"WAVELET\",\n",
    "                      default='db2', help=\"wavelet name [default: %default]\")\n",
    "    parser.add_option(\"-l\", \"--level\", dest=\"level\", metavar=\"LEVEL\",\n",
    "                      type=\"int\", default=4,\n",
    "                      help=\"decomposition level [default: %default]\")\n",
    "    parser.add_option(\"-m\", \"--mode\", dest=\"mode\", metavar=\"MODE\",\n",
    "                      default='symmetric',\n",
    "                      help=\"decomposition mode. Adjust this if\"\n",
    "                      \" getting edge artifacts [default: %default]\")\n",
    "    parser.add_option(\"-x\", \"--base_gain\", dest=\"base_gain\", metavar=\"BG\",\n",
    "                      type=\"float\", default=None,\n",
    "                      help=\"Base image gain [default: %default]\")\n",
    "    parser.add_option(\"-y\", \"--texture_gain\", dest=\"texture_gain\",\n",
    "                      metavar=\"TG\", type=\"float\", default=None,\n",
    "                      help=\"Texture image gain [default: %default]\")\n",
    "    parser.add_option(\"--timeit\", dest=\"timeit\", action=\"store_true\",\n",
    "                      default=False, help=\"time blending operations\")\n",
    "\n",
    "    (options, args) = parser.parse_args()\n",
    "\n",
    "    if None in (options.base, options.texture, options.output):\n",
    "        parser.print_help()\n",
    "        sys.exit(-1)\n",
    "\n",
    "    base = load_image(options.base)\n",
    "    texture = load_image(options.texture, base.mode, base.size)\n",
    "\n",
    "    if options.timeit:\n",
    "        t = clock()\n",
    "\n",
    "    im = blend_images(base, texture, options.wavelet, options.level,\n",
    "                      options.mode, options.base_gain, options.texture_gain)\n",
    "\n",
    "    if options.timeit:\n",
    "        print(\"%.3fs\" % (clock() - t))\n",
    "\n",
    "    im.save(options.output)\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
